Better Xen backtraces in debug builds (follow the
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 1 Sep 2005 15:31:12 +0000 (15:31 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 1 Sep 2005 15:31:12 +0000 (15:31 +0000)
stack frame pointer).

Signed-off-by: Keir Fraser <keir@xensource.com>
xen/Rules.mk
xen/arch/x86/Rules.mk
xen/arch/x86/boot/x86_32.S
xen/arch/x86/boot/x86_64.S
xen/arch/x86/traps.c
xen/arch/x86/x86_32/traps.c
xen/arch/x86/x86_64/traps.c
xen/include/asm-x86/processor.h
xen/include/asm-x86/x86_32/asm_defns.h
xen/include/asm-x86/x86_64/asm_defns.h

index 511184b08ee24557fb52c822939c153258c992d4..4c3cb8db4ea7f35ca002e1fc18c6fe3687ef38ce 100644 (file)
@@ -7,7 +7,6 @@ debug       ?= n
 perfc       ?= n
 perfc_arrays?= n
 trace       ?= n
-optimize    ?= y
 domu_debug  ?= n
 crash_debug ?= n
 
index 0675d763cda0e726e0192a2e16a862cf05b03510..e73be57bbca98805e217e705a6f7bd21492d1f10 100644 (file)
@@ -13,10 +13,8 @@ CFLAGS  += -I$(BASEDIR)/include
 CFLAGS  += -I$(BASEDIR)/include/asm-x86/mach-generic
 CFLAGS  += -I$(BASEDIR)/include/asm-x86/mach-default
 
-ifeq ($(optimize),y)
+ifneq ($(debug),y)
 CFLAGS  += -O3 -fomit-frame-pointer
-else
-x86_32/usercopy.o: CFLAGS += -O1
 endif
 
 # Prevent floating-point variables from creeping into Xen.
index fafc707beada4629471143b0d1af90deacdd7c0c..ca0c43555a540e8ac3862b63ed16c2194ac8792a 100644 (file)
@@ -9,6 +9,8 @@
                .text
 
 ENTRY(start)
+ENTRY(stext)
+ENTRY(_stext)
         jmp __start
 
         .align 4
@@ -260,6 +262,3 @@ ENTRY(idle_pg_table_l2) # Initial page directory is 4kB
         .org 0x2000 + STACK_SIZE + PAGE_SIZE
 
 #endif /* CONFIG_X86_PAE */
-
-ENTRY(stext)
-ENTRY(_stext)
index 85c599f5367fb72570ef985ce20c1c270af3c740..fbe5311124fd0ca86ba4f167b1c45935b3b927f9 100644 (file)
@@ -10,6 +10,8 @@
         .code32
 
 ENTRY(start)
+ENTRY(stext)
+ENTRY(_stext)
         jmp __start
 
         .org    0x004
@@ -267,5 +269,3 @@ ENTRY(idle_pg_table_l2)
 
         .org 0x4000 + STACK_SIZE + PAGE_SIZE
         .code64
-ENTRY(stext)
-ENTRY(_stext)
index 107485a5d9ab785077697aa8be498f7cfa229f86..865204a72d2748f324726c0dedd2450b2174c325 100644 (file)
@@ -100,7 +100,14 @@ unsigned long do_get_debugreg(int reg);
 
 static int debug_stack_lines = 20;
 integer_param("debug_stack_lines", debug_stack_lines);
-#define stack_words_per_line (32 / BYTES_PER_LONG)
+
+#ifdef CONFIG_X86_32
+#define stack_words_per_line 8
+#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)&regs->esp)
+#else
+#define stack_words_per_line 4
+#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)regs->esp)
+#endif
 
 int is_kernel_text(unsigned long addr)
 {
@@ -118,17 +125,16 @@ unsigned long kernel_text_end(void)
     return (unsigned long) &_etext;
 }
 
-void show_guest_stack(void)
+static void show_guest_stack(struct cpu_user_regs *regs)
 {
     int i;
-    struct cpu_user_regs *regs = guest_cpu_user_regs();
     unsigned long *stack = (unsigned long *)regs->esp, addr;
 
     printk("Guest stack trace from "__OP"sp=%p:\n   ", stack);
 
     for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )
     {
-        if ( ((long)stack & (STACK_SIZE-1)) == 0 )
+        if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )
             break;
         if ( get_user(addr, stack) )
         {
@@ -148,38 +154,98 @@ void show_guest_stack(void)
     printk("\n");
 }
 
-void show_trace(unsigned long *esp)
+#ifdef NDEBUG
+
+static void show_trace(struct cpu_user_regs *regs)
 {
-    unsigned long *stack = esp, addr;
-    int i = 0;
+    unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;
 
-    printk("Xen call trace from "__OP"sp=%p:\n   ", stack);
+    printk("Xen call trace:\n   ");
 
-    while ( ((long) stack & (STACK_SIZE-1)) != 0 )
+    printk("[<%p>]", _p(regs->eip));
+    print_symbol(" %s\n   ", regs->eip);
+
+    while ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) != 0 )
     {
         addr = *stack++;
         if ( is_kernel_text(addr) )
         {
             printk("[<%p>]", _p(addr));
             print_symbol(" %s\n   ", addr);
-            i++;
         }
     }
-    if ( i == 0 )
-        printk("Trace empty.");
+
+    printk("\n");
+}
+
+#else
+
+static void show_trace(struct cpu_user_regs *regs)
+{
+    unsigned long *frame, next, addr, low, high;
+
+    printk("Xen call trace:\n   ");
+
+    printk("[<%p>]", _p(regs->eip));
+    print_symbol(" %s\n   ", regs->eip);
+
+    /* Bounds for range of valid frame pointer. */
+    low  = (unsigned long)(ESP_BEFORE_EXCEPTION(regs) - 2);
+    high = (low & ~(STACK_SIZE - 1)) + (STACK_SIZE - sizeof(struct cpu_info));
+
+    /* The initial frame pointer. */
+    next = regs->ebp;
+
+    for ( ; ; )
+    {
+        /* Valid frame pointer? */
+        if ( (next < low) || (next > high) )
+        {
+            /*
+             * Exception stack frames have a different layout, denoted by an
+             * inverted frame pointer.
+             */
+            next = ~next;
+            if ( (next < low) || (next > high) )
+                break;
+            frame = (unsigned long *)next;
+            next  = frame[0];
+            addr  = frame[(offsetof(struct cpu_user_regs, eip) -
+                           offsetof(struct cpu_user_regs, ebp))
+                         / BYTES_PER_LONG];
+        }
+        else
+        {
+            /* Ordinary stack frame. */
+            frame = (unsigned long *)next;
+            next  = frame[0];
+            addr  = frame[1];
+        }
+
+        printk("[<%p>]", _p(addr));
+        print_symbol(" %s\n   ", addr);
+
+        low = (unsigned long)&frame[2];
+    }
+
     printk("\n");
 }
 
-void show_stack(unsigned long *esp)
+#endif
+
+void show_stack(struct cpu_user_regs *regs)
 {
-    unsigned long *stack = esp, addr;
+    unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;
     int i;
 
+    if ( GUEST_MODE(regs) )
+        return show_guest_stack(regs);
+
     printk("Xen stack trace from "__OP"sp=%p:\n   ", stack);
 
     for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )
     {
-        if ( ((long)stack & (STACK_SIZE-1)) == 0 )
+        if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )
             break;
         if ( (i != 0) && ((i % stack_words_per_line) == 0) )
             printk("\n   ");
@@ -190,7 +256,7 @@ void show_stack(unsigned long *esp)
         printk("Stack empty.");
     printk("\n");
 
-    show_trace(esp);
+    show_trace(regs);
 }
 
 /*
index 34c7871a2c80582626827d7221be1b1045b0ec97..091b4e11de35c8a3f457d2ada0519b45971b003d 100644 (file)
@@ -79,11 +79,8 @@ void show_registers(struct cpu_user_regs *regs)
            "ss: %04lx   cs: %04lx\n",
            ds, es, fs, gs, ss, cs);
 
-    if ( GUEST_MODE(regs) )
-        show_guest_stack();
-    else
-        show_stack((unsigned long *)&regs->esp);
-} 
+    show_stack(regs);
+}
 
 void show_page_walk(unsigned long addr)
 {
index 5e9701a1f6c6af8b815fa9c64b0f238db3f1241b..7fee6016994f8536ac420d03fa2c43718dfe8832 100644 (file)
@@ -32,10 +32,7 @@ void show_registers(struct cpu_user_regs *regs)
            regs->r12, regs->r13, regs->r14);
     printk("r15: %016lx\n", regs->r15);
 
-    if ( GUEST_MODE(regs) )
-        show_guest_stack();
-    else
-        show_stack((unsigned long *)regs->rsp);
+    show_stack(regs);
 }
 
 void show_page_walk(unsigned long addr)
index 82b8cbce62777c38ab7adfbca489b8dddfb63410..b312175e8c3b6c9922941bc9c73851b354a8db48 100644 (file)
@@ -496,9 +496,7 @@ extern inline void prefetchw(const void *x)
 
 #endif
 
-void show_guest_stack();
-void show_trace(unsigned long *esp);
-void show_stack(unsigned long *esp);
+void show_stack(struct cpu_user_regs *regs);
 void show_registers(struct cpu_user_regs *regs);
 void show_page_walk(unsigned long addr);
 asmlinkage void fatal_trap(int trapnr, struct cpu_user_regs *regs);
index d0243d4a52be3f04651879b22f35a4bcf67bb053..c3772c6b1c573e9d049552110ee6e3136243ab18 100644 (file)
@@ -1,10 +1,20 @@
 #ifndef __X86_32_ASM_DEFNS_H__
 #define __X86_32_ASM_DEFNS_H__
 
+#ifndef NDEBUG
+/* Indicate special exception stack frame by inverting the frame pointer. */
+#define SETUP_EXCEPTION_FRAME_POINTER           \
+        movl  %esp,%ebp;                        \
+        notl  %ebp
+#else
+#define SETUP_EXCEPTION_FRAME_POINTER
+#endif
+
 #define __SAVE_ALL_PRE                                  \
         cld;                                            \
         pushl %eax;                                     \
         pushl %ebp;                                     \
+        SETUP_EXCEPTION_FRAME_POINTER;                  \
         pushl %edi;                                     \
         pushl %esi;                                     \
         pushl %edx;                                     \
index ff1d4927e05f25c070ecbced725a81a915097b8c..d11af7228a44a471ac32e25ffa3a746dc4fc86d1 100644 (file)
@@ -1,6 +1,15 @@
 #ifndef __X86_64_ASM_DEFNS_H__
 #define __X86_64_ASM_DEFNS_H__
 
+#ifndef NDEBUG
+/* Indicate special exception stack frame by inverting the frame pointer. */
+#define SETUP_EXCEPTION_FRAME_POINTER           \
+        movq  %rsp,%rbp;                        \
+        notq  %rbp
+#else
+#define SETUP_EXCEPTION_FRAME_POINTER
+#endif
+
 #define SAVE_ALL                                \
         cld;                                    \
         pushq %rdi;                             \
@@ -14,6 +23,7 @@
         pushq %r11;                             \
         pushq %rbx;                             \
         pushq %rbp;                             \
+        SETUP_EXCEPTION_FRAME_POINTER;          \
         pushq %r12;                             \
         pushq %r13;                             \
         pushq %r14;                             \